﻿using GBT.Client.FileOperation;
using GBT.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GBT.Client.Forms
{
    public partial class FileManagement : Form
    {
        public FileManagement()
        {
            InitializeComponent();

            tsmiLargeIcons.Click += TsmiLargeIcons_Click;

            tsmiDetail.Click += TsmiDetail_Click;

            tsmiEdit.Click += TsmiEdit_Click;

            tsmiDownload.Click += TsmiDownload_Click;

            tsmiUpload.Click += TsmiUpload_Click;

            tsmiUploadDirectory.Click += TsmiUploadDirectory_Click;

            tsmiDelete.Click += TsmiDelete_Click;

            tsmiCat.Click += TsmiCat_Click;

            tsmiCopy.Click += TsmiCopy_Click;

            tsmiPaste.Click += TsmiPaste_Click;

            tsmiNewDirectory.Click += TsmiNewDirectory_Click;

            tsmiRename.Click += TsmiRename_Click;

            tsmiSignOut.Click += TsmiSignOut_Click;

            tsmiOpenDownloadDirectory.Click += TsmiOpenDownloadDirectory_Click;
        }

        public FtpOperation ftpOperation { get; set; }

        //public string root { get; set; } = "Harry Yang";
        public string root { get; set; }

        private enum OptType
        {
            None,
            Rename,
            Cat,
            Copy,
            Edit,
            Download,
            Upload,
            Delete,
            Drag,
        }

        #region Entity
        private static class OptObject
        {
            public static List<ObjectInfo> OrgPaths { get; set; } = new List<ObjectInfo>();

            public static string CurPath { get; set; }

            public static OptType Type { get; set; }
        }

        private class ObjectInfo
        {
            public string Path { get; set; }
            public string RemotePath { get; set; }

            public string Name { get; set; }

            public string Tag { get; set; }
        }
        #endregion

        private void FileManagement_Load(object sender, EventArgs e)
        {
            txtFilePath.Text = root;
            GetFtpInfomation(lvDetail.View, root, treeNode: tvTreeDirectory.Nodes[0]);
        }

        private void TsmiSignOut_Click(object sender, EventArgs e)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            Program.isLogin = false;
            ConfigHelper.SetValue("Password", "");
            ConfigHelper.SetValue("IsRememberMe", "false");
            keyValuePairs.Add("Password", "");
            keyValuePairs.Add("IsRememberMe", "false");
            ConfigHelper.SaveClientConfig(keyValuePairs);
            root = "";
            this.Close();
        }

        Login login;

        private void FileManagement_FormClosing(object sender, FormClosingEventArgs e)
        {
            Program.isLogin = false;
            if (string.IsNullOrEmpty(root))
            {
                login = new Login();
                login.Show();
            }
        }

        private void TsmiRename_Click(object sender, EventArgs e)
        {
            OptObject.Type = OptType.Rename;
            //TODO: Rename
            string orgPath = txtFilePath.Text + "\\" + lvDetail.SelectedItems[0].Text;
            Rename rename = new Rename();
            if (rename.ShowDialog() == DialogResult.OK)
            {
                string newPath = txtFilePath.Text + "\\" + rename.NewFileName + orgPath.ToExtension();
                ftpOperation.Rename(orgPath, newPath);
                ListRefresh();
            }
        }

        private void Paste(string curPath)
        {
            tspbProgress.Visible = true;
            Task.Run(() =>
            {
                lock (OptObject.OrgPaths)
                {
                    try
                    {
                        foreach (ObjectInfo orgPath in OptObject.OrgPaths)
                        {
                            OptObject.CurPath = curPath + "\\" + orgPath.Name;
                            switch (OptObject.Type)
                            {
                                case OptType.Cat:
                                    if (orgPath.Path != OptObject.CurPath)
                                        ftpOperation.MoveDirectoryOrFile(orgPath.RemotePath, OptObject.CurPath, orgPath.Tag);
                                    else
                                        MessageBox.Show("Unable to move files in the same folder!", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                    break;
                                case OptType.Drag:
                                    if (orgPath.Path != OptObject.CurPath)
                                        ftpOperation.MoveDirectoryOrFile(orgPath.RemotePath, OptObject.CurPath, orgPath.Tag);
                                    else
                                        MessageBox.Show("Unable to move files in the same folder!", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                    break;
                                case OptType.Copy:

                                    break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace, "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }).ContinueWith(t =>
            {
                OptObject.OrgPaths.Clear();
                if (lvDetail.InvokeRequired)
                {
                    lvDetail.Invoke(new Action(delegate
                    {
                        tspbProgress.Visible = false;
                        OptObject.Type = OptType.None;
                        IsSleep = false;
                        ListRefresh();
                    }));
                }
            });
        }

        private void TsmiPaste_Click(object sender, EventArgs e)
        {
            string curPath = txtFilePath.Text;
            Paste(curPath);
        }

        private void SelectedFiles()
        {
            ObjectInfo remoteFileInfo;
            OptObject.OrgPaths.Clear();
            string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + root;
            if (!ftpOperation.IsDirectoryExists(path))
            {
                ftpOperation.CreateDirectory(path);
            }
            foreach (ListViewItem listViewItem in lvDetail.SelectedItems)
            {
                if (listViewItem.Text != "Recycled")
                {
                    remoteFileInfo = new ObjectInfo();
                    remoteFileInfo.Path = path + "\\" + listViewItem.Text;
                    remoteFileInfo.Name = listViewItem.Text;
                    remoteFileInfo.RemotePath = txtFilePath.Text + "\\" + listViewItem.Text;
                    remoteFileInfo.Tag = listViewItem.Tag as string;
                    OptObject.OrgPaths.Add(remoteFileInfo);
                }
            }
        }

        private void TsmiNewDirectory_Click(object sender, EventArgs e)
        {
            string pathDir = txtFilePath.Text;
            string directoryName = "";
            NewDirectory newDirectory = new NewDirectory();
            if (newDirectory.ShowDialog() == DialogResult.OK)
            {
                directoryName = newDirectory.DirectoryName;
                string NewDirectoryPath = pathDir + "\\" + directoryName;
                //不存在文件夹才创建
                if (!ftpOperation.IsDirectoryExists(NewDirectoryPath))
                {
                    ftpOperation.CreateDirectory(NewDirectoryPath);
                }
                ListRefresh();
            }
        }

        private void TsmiCopy_Click(object sender, EventArgs e)
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                SelectedFiles();
                OptObject.Type = OptType.Copy;
                //下载文件到本地后 添加到本地 粘贴板
                Download(OptObject.OrgPaths);
            }
        }

        private void TsmiCat_Click(object sender, EventArgs e)
        {
            SelectedFiles();
            OptObject.Type = OptType.Cat;
        }

        private void ListRefresh()
        {
            lvDetail.Items.Clear();
            string path = txtFilePath.Text;
            GetFtpInfomation(lvDetail.View, path: path);
        }

        private void DeleteDirectoryOrFile()
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                OptObject.Type = OptType.Delete;
                //TODO: Delete
                string path = txtFilePath.Text;
                List<ObjectInfo> fileInfos = new List<ObjectInfo>();
                ObjectInfo fileInfo = new ObjectInfo();
                foreach (ListViewItem listViewItem in lvDetail.SelectedItems)
                {
                    fileInfo = new ObjectInfo();
                    fileInfo.Path = path + "\\" + listViewItem.Text;
                    fileInfo.Name = listViewItem.Text;
                    fileInfo.Tag = listViewItem.Tag as string;
                    fileInfos.Add(fileInfo);
                }
                Task.Run(() =>
                {
                    try
                    {
                        foreach (ObjectInfo fileInfo1 in fileInfos)
                        {
                            ftpOperation.DeleteDerectoryOrFile(fileInfo1.Path, fileInfo1.Tag);
                        }
                    }
                    catch { }
                }).ContinueWith(t =>
                {
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            tspbProgress.Visible = false;
                            ListRefresh();
                        }));
                    }
                });
            }
        }

        private void TsmiDelete_Click(object sender, EventArgs e)
        {
            //删除文件时判断是否存在回收站，不存在则创建回收站
            if (!ftpOperation.IsDirectoryExists(root + "\\Recycled"))
            {
                ftpOperation.CreateDirectory(root + "\\Recycled");
            }

            if (txtFilePath.Text.IsRecycled())
            {
                DialogResult dialogResult = MessageBox.Show("Are you sure to permanently delete files?", "TIPS", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                if (dialogResult == DialogResult.Yes)
                {
                    //在回收站中即可永久删除
                    DeleteDirectoryOrFile();
                }
            }
            else
            {
                if (!tspbProgress.Visible)
                {
                    tspbProgress.Visible = true;
                    Task.Run(() =>
                    {
                        if (lvDetail.InvokeRequired)
                        {
                            lvDetail.Invoke(new Action(delegate
                            {
                                SelectedFiles();
                            }));
                        }
                        lock (OptObject.OrgPaths)
                        {
                            //移动被删除的文件到回收站
                            foreach (ObjectInfo orgPath in OptObject.OrgPaths)
                            {
                                OptObject.CurPath = root + "\\Recycled" + "\\" + orgPath.Name;
                                ftpOperation.MoveDirectoryOrFile(orgPath.RemotePath, OptObject.CurPath, orgPath.Tag);
                            }
                        }
                    }).ContinueWith(t =>
                    {
                        if (lvDetail.InvokeRequired)
                        {
                            lvDetail.Invoke(new Action(delegate
                            {
                                tspbProgress.Visible = false;
                                ListRefresh();
                            }));
                        }
                    });
                }
            }
        }

        private void Download(List<ObjectInfo> fileInfos)
        {
            string resultMessage = "";
            System.Collections.Specialized.StringCollection strcoll = new System.Collections.Specialized.StringCollection();
            Task.Run(() =>
            {
                foreach (ObjectInfo fileInfo in fileInfos)
                {
                    try
                    {
                        var ftpStatus = ftpOperation.Download(fileInfo.Path, fileInfo.RemotePath.EnsurePrefix("/"), fileInfo.Tag);
                        if (ftpStatus)
                        {
                            resultMessage += fileInfo.Tag + " " + fileInfo.Name + " was downloaded successfully！" + Environment.NewLine;
                            if (fileInfos.Count == 1 && OptObject.Type == OptType.Edit)
                            {
                                Process.Start("explorer.exe", "\"" + fileInfo.Path + "\"");
                            }
                            else if (OptObject.Type == OptType.Copy)
                            {
                                strcoll.Add(fileInfo.Path);
                            }
                        }
                        else
                        {
                            resultMessage += fileInfo.Tag + " " + fileInfo.Name + " failed to download！" + Environment.NewLine;
                        }
                    }
                    catch (Exception ex)
                    {
                        resultMessage += ex.Message + Environment.NewLine + ex.InnerException + Environment.NewLine;
                    }
                }
            }).ContinueWith(t =>
            {
                if (OptObject.Type == OptType.Copy && strcoll.Count > 0)
                {
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            Clipboard.SetFileDropList(strcoll);
                            tspbProgress.Visible = false;
                        }));
                    }
                    MessageBox.Show("Copy file successfully！", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else if (!string.IsNullOrEmpty(resultMessage))
                {
                    if (OptObject.Type == OptType.Download)
                    {
                        MessageBox.Show(resultMessage, "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            tspbProgress.Visible = false;
                        }));
                    }
                }
                else
                {
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            tspbProgress.Visible = false;
                        }));
                    }
                }
            });
        }

        private void Upload(List<ObjectInfo> uploadEs)
        {
            OptObject.Type = OptType.Upload;
            string currentRemotePath = "";
            string resultMessage = "";
            Task task = Task.Run(() =>
            {
                try
                {
                    foreach (ObjectInfo uploadE in uploadEs)
                    {
                        currentRemotePath = txtFilePath.Text + "\\" + uploadE.Name;
                        bool ftpStatus = ftpOperation.Upload(uploadE.Path, currentRemotePath.EnsurePrefix("/"), uploadE.Tag);
                        if (ftpStatus)
                        {
                            resultMessage += uploadE.Tag + " " + uploadE.Name + " has been uploaded successfully！" + Environment.NewLine;
                        }
                        else
                        {
                            resultMessage += uploadE.Tag + " " + uploadE.Name + " upload failed！" + Environment.NewLine;
                        }
                    }
                }
                catch (Exception ex)
                {
                    resultMessage += ex.Message + Environment.NewLine + ex.InnerException + Environment.NewLine;
                }
            }).ContinueWith(t =>
            {
                if (!string.IsNullOrEmpty(resultMessage))
                {
                    //上传成功后 刷新
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            tspbProgress.Visible = false;
                            ListRefresh();
                        }));
                    }
                    MessageBox.Show(resultMessage, "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            tspbProgress.Visible = false;
                        }));
                    }
                }
            });
        }

        private void TsmiUpload_Click(object sender, EventArgs e)
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                List<ObjectInfo> uploadEs = new List<ObjectInfo>();
                ObjectInfo uploadE = new ObjectInfo();
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "(*.*)|*.*";
                openFileDialog.Multiselect = true;
                string newPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + root;
                if (!ftpOperation.IsDirectoryExists(newPath))
                {
                    ftpOperation.CreateDirectory(newPath);
                }
                openFileDialog.InitialDirectory = newPath;
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    foreach (string fileName in openFileDialog.SafeFileNames)
                    {
                        uploadE = new ObjectInfo();
                        uploadE.Path = openFileDialog.FileNames.Where(t => t.Contains(fileName)).FirstOrDefault();
                        uploadE.Name = fileName;
                        uploadE.Tag = openFileDialog.FileNames.Where(t => t.Contains(fileName)).FirstOrDefault().GetObjectType();
                        uploadEs.Add(uploadE);
                    }
                    // TODO: Upload
                    Upload(uploadEs);
                }
                else
                {
                    tspbProgress.Visible = false;
                }
            }
            else
            {
                MessageBox.Show("Uploading, please hold on!!!", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void TsmiUploadDirectory_Click(object sender, EventArgs e)
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                List<ObjectInfo> uploadEs = new List<ObjectInfo>();
                ObjectInfo uploadE = new ObjectInfo();
                FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
                string newPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + root;
                if (!ftpOperation.IsDirectoryExists(newPath))
                {
                    ftpOperation.CreateDirectory(newPath);
                }
                folderBrowser.SelectedPath = newPath;
                if (folderBrowser.ShowDialog() == DialogResult.OK)
                {
                    uploadE = new ObjectInfo();
                    uploadE.Path = folderBrowser.SelectedPath;
                    uploadE.Name = uploadE.Path.GetDirectoryNameOrFileName();
                    uploadE.Tag = folderBrowser.SelectedPath.GetObjectType();
                    uploadEs.Add(uploadE);
                    // TODO: Upload
                    Upload(uploadEs);
                }
                else
                {
                    tspbProgress.Visible = false;
                }
            }
            else
            {
                MessageBox.Show("Uploading, please hold on!!!", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void TsmiDownload_Click(object sender, EventArgs e)
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                OptObject.Type = OptType.Download;
                // TODO: Download
                List<ObjectInfo> fileInfos = new List<ObjectInfo>();
                ObjectInfo fileInfo;

                string remotePath = txtFilePath.Text + "\\";
                FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
                string newPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + root;
                if (!ftpOperation.IsDirectoryExists(newPath))
                {
                    ftpOperation.CreateDirectory(newPath);
                }
                folderBrowserDialog.SelectedPath = newPath;
                if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
                {
                    foreach (ListViewItem listViewItem in lvDetail.SelectedItems)
                    {
                        fileInfo = new ObjectInfo();
                        fileInfo.Path = folderBrowserDialog.SelectedPath + "\\" + listViewItem.Text;
                        fileInfo.Name = listViewItem.Text;
                        fileInfo.RemotePath = txtFilePath.Text + "\\" + listViewItem.Text;
                        fileInfo.Tag = listViewItem.Tag as string;
                        fileInfos.Add(fileInfo);
                    }
                    Download(fileInfos);
                }
                else
                {
                    tspbProgress.Visible = false;
                }
            }
            else
            {
                MessageBox.Show("Downloading, please hold on!!!", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void TsmiOpenDownloadDirectory_Click(object sender, EventArgs e)
        {
            string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + root;
            if (!ftpOperation.IsDirectoryExists(path))
            {
                ftpOperation.CreateDirectory(path);
            }
            Process.Start("explorer.exe", path);
        }

        private void Edit()
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                OptObject.Type = OptType.Edit;
                //下载到临时目录并打开
                List<ObjectInfo> fileInfos = new List<ObjectInfo>();
                ObjectInfo fileInfo = new ObjectInfo();
                string newPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + root;
                if (!ftpOperation.IsDirectoryExists(newPath))
                {
                    ftpOperation.CreateDirectory(newPath);
                }
                fileInfo.Path = newPath + "\\" + lvDetail.SelectedItems[0].Text;
                //fileInfo.FilePath = Environment.GetEnvironmentVariable("TEMP") + "\\" + lvDetail.SelectedItems[0].Text;
                fileInfo.RemotePath = txtFilePath.Text + "\\" + lvDetail.SelectedItems[0].Text;
                fileInfo.Name = lvDetail.SelectedItems[0].Text;
                fileInfo.Tag = lvDetail.SelectedItems[0].Tag as string;
                fileInfos.Add(fileInfo);
                Download(fileInfos);
            }
            else
            {
                MessageBox.Show("Editing underway, please hold on!!!", "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void TsmiEdit_Click(object sender, EventArgs e)
        {
            // TODO: Edit
            Edit();
        }

        private void TsmiDetail_Click(object sender, EventArgs e)
        {
            lvDetail.FullRowSelect = true;
            lvDetail.View = View.Details;
            lvDetail.Columns.Clear();
            lvDetail.Columns.Add("Name");
            lvDetail.Columns.Add("Type");
            lvDetail.Columns.Add("Data Modified");
            lvDetail.Columns.Add("Size");
            lvDetail.AddColumnSort();
            string path = txtFilePath.Text;
            GetFtpInfomation(View.Details, path: path);
        }

        private void TsmiLargeIcons_Click(object sender, EventArgs e)
        {
            lvDetail.View = View.LargeIcon;
            lvDetail.Columns.Clear();
            string path = txtFilePath.Text;
            GetFtpInfomation(View.LargeIcon, path: path);
        }

#pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
        private void GetFtpInfomation(View view, string? path = null, TreeNode treeNode = null)
#pragma warning restore CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
        {
            if (!tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                CancellationTokenSource ts = new CancellationTokenSource();
                CancellationToken c = ts.Token;
                List<TreeNode> treeNodes = new List<TreeNode>();
                List<ListViewItem> listViewItems = new List<ListViewItem>();
                string message = "";
                Task task = Task.Run(() =>
                {
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            imageList2.Images.Clear();
                            imageList4.Images.Clear();
                            foreach (Image image in imageList3.Images)
                            {
                                imageList2.Images.Add(image);
                                imageList4.Images.Add(image);
                            }
                        }));
                    }
                    try
                    {
                        message = ftpOperation.GetDirectory(ref treeNodes, ref listViewItems, path, view);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace, "TIPS", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }).ContinueWith(t =>
                {
                    if (tvTreeDirectory.InvokeRequired && treeNode != null)
                    {
                        tvTreeDirectory.Invoke(new Action(delegate
                        {
                            TreeNode rootNode = treeNode;
                            foreach (TreeNode treeNode in treeNodes)
                            {
                                if (treeNode.Text == "Recycled")
                                {
                                    treeNode.ImageIndex = 6;
                                    treeNode.SelectedImageIndex = 6;
                                }
                                rootNode.Nodes.Add(treeNode);
                            }
                        }));
                    }
                    if (lvDetail.InvokeRequired)
                    {
                        lvDetail.Invoke(new Action(delegate
                        {
                            try
                            {
                                foreach (ImageEntity image in ImageInfo.imageEntityList.OrderBy(t => t.imageIndex))
                                {
                                    imageList2.Images.Add(image.image);
                                    imageList4.Images.Add(image.image);
                                }
                                lvDetail.Items.Clear();
                                foreach (ListViewItem listViewItem in listViewItems)
                                {
                                    lvDetail.Items.Add(listViewItem);
                                }
                                lvDetail.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent);
                                lvDetail.AutoResizeColumn(2, ColumnHeaderAutoResizeStyle.ColumnContent);
                            }
                            catch { }
                        }));
                    }
                    if (statusStrip1.InvokeRequired)
                    {
                        statusStrip1.Invoke(new Action(delegate
                        {
                            tsslMessage.Text = message;
                            tspbProgress.Visible = false;
                        }));
                    }
                });
            }
            else
            {

            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            ListRefresh();
        }

        private void lvDetail_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                ListViewItem listViewItem = lvDetail.SelectedItems[0];
                string remotePath = txtFilePath.Text + "\\" + listViewItem.Text;
                if (listViewItem.Tag as string == "directory")
                {
                    //是文件夹才能双击进入
                    lvDetail.Items.Clear();
                    txtFilePath.Text = remotePath;
                    GetFtpInfomation(lvDetail.View, path: remotePath);
                }
                else if (listViewItem.Tag as string == "file")
                {
                    //下载到临时目录
                    Edit();
                }
            }
            catch { }
        }

        private void btnUp_Click(object sender, EventArgs e)
        {
            lvDetail.Items.Clear();
            string path = txtFilePath.Text;
            path = path.GetParentDirectory(root);
            txtFilePath.Text = path;
            GetFtpInfomation(lvDetail.View, path: path);
        }

#pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
        private void MenuControl(bool isEnable, string? tag = null)
#pragma warning restore CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
        {
            tsmiEdit.Enabled = lvDetail.SelectedItems.Count == 1 && tag == "file";
            tsmiDownload.Enabled = isEnable;
            tsmiUpload.Enabled = !isEnable;
            tsmiUploadDirectory.Enabled = !isEnable;
            tsmiDelete.Enabled = !lvDetail.IsRecycled() && lvDetail.SelectedItems.Count > 0;
            tsmiCat.Enabled = !lvDetail.IsRecycled() && lvDetail.SelectedItems.Count > 0;
            tsmiCopy.Enabled = isEnable;
            tsmiPaste.Enabled = !isEnable && OptObject.OrgPaths.Count > 0;
            tsmiRename.Enabled = !lvDetail.IsRecycled() && lvDetail.SelectedItems.Count > 0;

            tsmiOpenDownloadDirectory.Visible = true;
            tsmiEdit.Visible = true;
            tsmiDownload.Visible = true;
            tsmiUpload.Visible = true;
            tsmiUploadDirectory.Visible = true;
            tsmiCopy.Visible = true;
            toolStripSeparator1.Visible = true;
            toolStripSeparator2.Visible = true;
            tsmiNewDirectory.Visible = true;
            tsmiPaste.Visible = true;
            tsmiRename.Visible = true;
            if (txtFilePath.Text.IsRecycled())
            {
                tsmiOpenDownloadDirectory.Visible = false;
                tsmiEdit.Visible = false;
                tsmiDownload.Visible = false;
                tsmiUpload.Visible = false;
                tsmiUploadDirectory.Visible = false;
                tsmiCopy.Visible = false;
                toolStripSeparator1.Visible = false;
                toolStripSeparator2.Visible = false;
                tsmiNewDirectory.Visible = false;
                tsmiPaste.Visible = false;
                tsmiRename.Visible = false;
            }
        }

        private void lvDetail_MouseUp(object sender, MouseEventArgs e)
        {
            if (lvDetail.SelectedItems.Count > 0)
            {
                ListViewItem listViewItem = lvDetail.SelectedItems?[0];
                if (e.Button == MouseButtons.Right)
                {
                    if (listViewItem == null)
                    {
                        MenuControl(false, listViewItem.Tag as string);
                    }
                    else
                    {
                        MenuControl(true, listViewItem.Tag as string);
                    }
                }
            }
            else
            {
                MenuControl(false);
            }
        }

        private void tvTreeDirectory_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (!tspbProgress.Visible)
            {
                lvDetail.Items.Clear();
                tvTreeDirectory.SelectedNode.Nodes.Clear();
                TreeNode selectedNode = tvTreeDirectory.SelectedNode;
                string path = selectedNode.FullPath.Replace("Root Directory", root);
                if (string.IsNullOrWhiteSpace(path) || path == "\\")
                {
                    path = "\\" + root;
                    txtFilePath.Text = path;
                }
                else
                    txtFilePath.Text = path;
                GetFtpInfomation(lvDetail.View, path, selectedNode);
            }
        }

        private void lvDetail_DragEnter(object sender, DragEventArgs e)
        {
            //e.Effect = DragDropEffects.All;
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Link;
            }
            else if (OptObject.Type == OptType.Drag)
            {
                e.Effect = DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private ListViewItem itemSelected = null;//定义拖动到位置的item

        private void lvDetail_ItemDrag(object sender, ItemDragEventArgs e)
        {
            OptObject.Type = OptType.Drag;
            SelectedFiles();
            lvDetail.DoDragDrop(e.Item, DragDropEffects.Move);
        }

        private bool IsSleep = false;

        private void lvDetail_DragOver(object sender, DragEventArgs e)
        {
            if (!IsSleep)
            {
                IsSleep = true;
                Thread.Sleep(1000);
            }
            Point ptScreen = new Point(e.X, e.Y);
            Point pt = lvDetail.PointToClient(ptScreen);
            e.Effect = DragDropEffects.Move;
            ListViewItem item = lvDetail.GetItemAt(pt.X, pt.Y);
            if (item != null)
            {
                OptObject.Type = OptType.Drag;
                item.Selected = true;
                itemSelected = item;
            }
            else
            {
                OptObject.Type = OptType.None;
                if (itemSelected != null)
                {
                    itemSelected.Selected = false;
                }
                OptObject.OrgPaths.Clear();
            }
        }

        private void lvDetail_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop) && OptObject.Type != OptType.Drag && !tspbProgress.Visible)
            {
                tspbProgress.Visible = true;
                string[] filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
                List<ObjectInfo> fileInfos = new List<ObjectInfo>();
                ObjectInfo fileInfo = new ObjectInfo();
                foreach (string filePath in filePaths)
                {
                    //多文件处理
                    fileInfo = new ObjectInfo();
                    fileInfo.Path = filePath;
                    fileInfo.Name = Path.GetFileName(filePath);
                    fileInfo.Tag = filePath.GetObjectType();
                    fileInfos.Add(fileInfo);
                }
                Upload(fileInfos);
            }
            else if (OptObject.Type == OptType.Drag && !tspbProgress.Visible && itemSelected != null)
            {
                string curPath = txtFilePath.Text + "\\" + itemSelected.Text;
                Paste(curPath);
            }
        }
    }
}
